#include "gtkwidgetprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkprivate.h"
+#include "gtkcenterboxprivate.h"
#include <string.h>
struct _GtkActionBarPrivate
{
- GtkWidget *box;
+ GtkWidget *center_box;
+ GtkWidget *start_box;
+ GtkWidget *end_box;
GtkWidget *revealer;
+
GtkCssGadget *gadget;
};
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (container));
- gtk_container_add (GTK_CONTAINER (priv->box), child);
+ /* Default for pack-type is start */
+ gtk_container_add (GTK_CONTAINER (priv->start_box), child);
}
static void
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (container));
- gtk_container_remove (GTK_CONTAINER (priv->box), child);
+ if (gtk_widget_get_parent (child) == priv->start_box)
+ gtk_container_remove (GTK_CONTAINER (priv->start_box), child);
+ else if (gtk_widget_get_parent (child) == priv->end_box)
+ gtk_container_remove (GTK_CONTAINER (priv->end_box), child);
+ else if (child == gtk_center_box_get_center_widget (GTK_CENTER_BOX (priv->center_box)))
+ gtk_center_box_set_center_widget (GTK_CENTER_BOX (priv->center_box), NULL);
+ else
+ g_warning ("Can't remove non-child %s %p from GtkActionBar %p",
+ G_OBJECT_TYPE_NAME (child), child, container);
}
static void
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (container));
if (include_internals)
- (* callback) (priv->revealer, callback_data);
- else if (priv->box)
- gtk_container_forall (GTK_CONTAINER (priv->box), callback, callback_data);
+ {
+ (*callback) (priv->revealer, callback_data);
+ }
+ else
+ {
+ if (priv->start_box != NULL)
+ gtk_container_forall (GTK_CONTAINER (priv->start_box), callback, callback_data);
+
+ if (gtk_center_box_get_center_widget (GTK_CENTER_BOX (priv->center_box)) != NULL)
+ (*callback) (gtk_center_box_get_center_widget (GTK_CENTER_BOX (priv->center_box)), callback_data);
+
+ if (priv->end_box != NULL)
+ gtk_container_forall (GTK_CONTAINER (priv->end_box), callback, callback_data);
+ }
}
static void
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (object));
- g_clear_object (&priv->gadget);
gtk_widget_unparent (priv->revealer);
+ g_clear_object (&priv->gadget);
+
G_OBJECT_CLASS (gtk_action_bar_parent_class)->finalize (object);
}
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (container));
- if (child == priv->revealer)
- g_param_value_set_default (pspec, value);
- else
- gtk_container_child_get_property (GTK_CONTAINER (priv->box),
- child,
- pspec->name,
- value);
+ switch (property_id)
+ {
+ case CHILD_PROP_PACK_TYPE:
+ if (gtk_widget_get_parent (child) == priv->start_box)
+ g_value_set_enum (value, GTK_PACK_START);
+ else if (gtk_widget_get_parent (child) == priv->end_box)
+ g_value_set_enum (value, GTK_PACK_END);
+ else /* Center widget */
+ g_value_set_enum (value, GTK_PACK_START);
+
+ break;
+
+ case CHILD_PROP_POSITION:
+ if (gtk_widget_get_parent (child) == priv->start_box)
+ {
+ int n;
+ gtk_container_child_get (GTK_CONTAINER (priv->start_box),
+ child,
+ "position", &n,
+ NULL);
+ g_value_set_int (value, n);
+ }
+ else if (gtk_widget_get_parent (child) == priv->end_box)
+ {
+ int n;
+ gtk_container_child_get (GTK_CONTAINER (priv->end_box),
+ child,
+ "position", &n,
+ NULL);
+ g_value_set_int (value, n);
+ }
+ else /* Center widget */
+ {
+ g_value_set_int (value, 0);
+ }
+ break;
+
+ default:
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+ break;
+ }
}
static void
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (container));
- if (child != priv->revealer)
- gtk_container_child_set_property (GTK_CONTAINER (priv->box),
- child,
- pspec->name,
- value);
+ switch (property_id)
+ {
+ case CHILD_PROP_PACK_TYPE:
+ if (gtk_widget_get_parent (child) == priv->start_box)
+ {
+ if (g_value_get_enum (value) == GTK_PACK_END)
+ {
+ g_object_ref (child);
+ gtk_container_remove (GTK_CONTAINER (priv->start_box), child);
+ gtk_box_pack_end (GTK_BOX (priv->end_box), child);
+ g_object_unref (child);
+ }
+ }
+ else if (gtk_widget_get_parent (child) == priv->end_box)
+ {
+ if (g_value_get_enum (value) == GTK_PACK_START)
+ {
+ g_object_ref (child);
+ gtk_container_remove (GTK_CONTAINER (priv->end_box), child);
+ gtk_container_add (GTK_CONTAINER (priv->start_box), child);
+ g_object_unref (child);
+ }
+ }
+ else
+ {
+ /* Ignore the center widget */
+ }
+
+ break;
+
+ case CHILD_PROP_POSITION:
+ if (gtk_widget_get_parent (child) == priv->start_box)
+ {
+ gtk_container_child_set (GTK_CONTAINER (priv->start_box),
+ child,
+ "position", g_value_get_int (value),
+ NULL);
+ }
+ else if (gtk_widget_get_parent (child) == priv->end_box)
+ {
+ gtk_container_child_set (GTK_CONTAINER (priv->end_box),
+ child,
+ "position", g_value_get_int (value),
+ NULL);
+ }
+ else
+ {
+ /* Ignore center widget */
+ }
+ break;
+
+ default:
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+ break;
+ }
}
static gboolean
int height,
gpointer data)
{
- GTK_WIDGET_CLASS (gtk_action_bar_parent_class)->snapshot (gtk_css_gadget_get_owner (gadget), snapshot);
+ GtkActionBar *self = GTK_ACTION_BAR (gtk_css_gadget_get_owner (gadget));
+ GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (self));
+
+ gtk_widget_snapshot_child (GTK_WIDGET (self), priv->revealer, snapshot);
return FALSE;
}
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (widget));
gtk_widget_size_allocate (priv->revealer, (GtkAllocation *)allocation);
-
- gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
+ gtk_widget_get_clip (priv->revealer, out_clip);
}
static void
}
}
+static void
+gtk_action_bar_destroy (GtkWidget *widget)
+{
+ GtkActionBar *self = GTK_ACTION_BAR (widget);
+ GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (self);
+
+ gtk_center_box_set_start_widget (GTK_CENTER_BOX (priv->center_box), NULL);
+ gtk_center_box_set_center_widget (GTK_CENTER_BOX (priv->center_box), NULL);
+ gtk_center_box_set_end_widget (GTK_CENTER_BOX (priv->center_box), NULL);
+
+ priv->start_box = NULL;
+ priv->end_box = NULL;
+
+ GTK_WIDGET_CLASS (gtk_action_bar_parent_class)->destroy (widget);
+}
+
static void
gtk_action_bar_class_init (GtkActionBarClass *klass)
{
widget_class->snapshot = gtk_action_bar_snapshot;
widget_class->size_allocate = gtk_action_bar_size_allocate;
widget_class->measure = gtk_action_bar_measure_;
+ widget_class->destroy = gtk_action_bar_destroy;
container_class->add = gtk_action_bar_add;
container_class->remove = gtk_action_bar_remove;
priv->revealer = gtk_revealer_new ();
gtk_widget_set_parent (priv->revealer, widget);
- priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- gtk_container_add (GTK_CONTAINER (priv->revealer), priv->box);
-
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->revealer), TRUE);
gtk_revealer_set_transition_type (GTK_REVEALER (priv->revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
+ priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ priv->end_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ priv->center_box = gtk_center_box_new ();
+ gtk_center_box_set_start_widget (GTK_CENTER_BOX (priv->center_box), priv->start_box);
+ gtk_center_box_set_end_widget (GTK_CENTER_BOX (priv->center_box), priv->end_box);
+
+ gtk_container_add (GTK_CONTAINER (priv->revealer), priv->center_box);
+
widget_node = gtk_widget_get_css_node (GTK_WIDGET (action_bar));
priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
GTK_WIDGET (action_bar),
const gchar *type)
{
GtkActionBar *action_bar = GTK_ACTION_BAR (buildable);
- GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (action_bar);
if (type && strcmp (type, "center") == 0)
- gtk_box_set_center_widget (GTK_BOX (priv->box), GTK_WIDGET (child));
+ gtk_action_bar_set_center_widget (action_bar, GTK_WIDGET (child));
else if (!type)
gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
else
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (action_bar);
- gtk_box_pack_start (GTK_BOX (priv->box), child);
+ gtk_container_add (GTK_CONTAINER (priv->start_box), child);
}
/**
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (action_bar);
- gtk_box_pack_end (GTK_BOX (priv->box), child);
+ gtk_box_pack_end (GTK_BOX (priv->end_box), child);
}
/**
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (action_bar);
- gtk_box_set_center_widget (GTK_BOX (priv->box), center_widget);
+ gtk_center_box_set_center_widget (GTK_CENTER_BOX (priv->center_box), center_widget);
}
/**
g_return_val_if_fail (GTK_IS_ACTION_BAR (action_bar), NULL);
- return gtk_box_get_center_widget (GTK_BOX (priv->box));
+ return gtk_center_box_get_center_widget (GTK_CENTER_BOX (priv->center_box));
}
/**
--- /dev/null
+
+#include "gtkcenterboxprivate.h"
+
+G_DEFINE_TYPE (GtkCenterBox, gtk_center_box, GTK_TYPE_WIDGET);
+
+
+static void
+gtk_center_box_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkCenterBox *self = GTK_CENTER_BOX (widget);
+ int min, nat, min_baseline, nat_baseline;
+
+ gtk_widget_measure (self->start_widget,
+ orientation,
+ for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+
+ if (self->center_widget)
+ {
+ gtk_widget_measure (self->center_widget,
+ orientation,
+ for_size,
+ &min, &nat,
+ &min_baseline, &nat_baseline);
+
+ /* XXX How are baselines even handled? */
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ *minimum = *minimum + min;
+ *natural = *natural + nat;
+ }
+ else /* GTK_ORIENTATION_VERTICAL */
+ {
+ *minimum = MAX (*minimum, min);
+ *natural = MAX (*minimum, nat);
+ }
+ }
+
+ gtk_widget_measure (self->end_widget,
+ orientation,
+ for_size,
+ &min, &nat,
+ &min_baseline, &nat_baseline);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ *minimum = *minimum + min;
+ *natural = *natural + nat;
+ }
+ else /* GTK_ORIENTATION_VERTICAL */
+ {
+ *minimum = MAX (*minimum, min);
+ *natural = MAX (*minimum, nat);
+ }
+
+}
+
+static void
+gtk_center_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkCenterBox *self = GTK_CENTER_BOX (widget);
+ GtkAllocation child_allocation;
+ GtkAllocation clip = *allocation;
+ GtkAllocation child_clip;
+ int start_size, end_size;
+ int min, nat;
+
+ GTK_WIDGET_CLASS (gtk_center_box_parent_class)->size_allocate (widget, allocation);
+
+
+ // TODO: Allocate natural sizes if possible?
+
+ /* Start Box */
+ gtk_widget_measure (self->start_widget, GTK_ORIENTATION_HORIZONTAL,
+ allocation->height,
+ &min, &nat, NULL, NULL);
+ child_allocation.x = allocation->x;
+ child_allocation.y = allocation->y;
+ child_allocation.width = min;
+ child_allocation.height = allocation->height;
+
+ gtk_widget_size_allocate (self->start_widget, &child_allocation);
+ gtk_widget_get_clip (self->start_widget, &child_clip);
+ gdk_rectangle_union (&clip, &clip, &child_clip);
+ start_size = child_allocation.width;
+
+
+ /* End Box */
+ gtk_widget_measure (self->end_widget, GTK_ORIENTATION_HORIZONTAL,
+ allocation->height,
+ &min, &nat, NULL, NULL);
+ child_allocation.x = allocation->x + allocation->width - min;
+ child_allocation.width = min;
+
+ gtk_widget_size_allocate (self->end_widget, &child_allocation);
+ gtk_widget_get_clip (self->end_widget, &child_clip);
+ gdk_rectangle_union (&clip, &clip, &child_clip);
+ end_size = child_allocation.width;
+
+ /* Center Widget */
+ if (self->center_widget)
+ {
+ gtk_widget_measure (self->center_widget, GTK_ORIENTATION_HORIZONTAL,
+ allocation->height,
+ &min, &nat, NULL, NULL);
+
+ child_allocation.x = (allocation->width / 2) - (min / 2);
+
+ /* Push in from start/end */
+ if (start_size > child_allocation.x)
+ child_allocation.x = start_size;
+ else if (allocation->width - end_size < child_allocation.x + min)
+ child_allocation.x = allocation->width - min - end_size;
+
+ child_allocation.x += allocation->x;
+ child_allocation.width = min;
+ gtk_widget_size_allocate (self->center_widget, &child_allocation);
+ gtk_widget_get_clip (self->center_widget, &child_clip);
+ gdk_rectangle_union (&clip, &clip, &child_clip);
+ }
+
+ gtk_widget_set_clip (widget, &clip);
+}
+
+static void
+gtk_center_box_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkCenterBox *self = GTK_CENTER_BOX (widget);
+
+ gtk_widget_snapshot_child (widget, self->start_widget, snapshot);
+
+ if (self->center_widget)
+ gtk_widget_snapshot_child (widget, self->center_widget, snapshot);
+
+ gtk_widget_snapshot_child (widget, self->end_widget, snapshot);
+}
+
+static void
+gtk_center_box_class_init (GtkCenterBoxClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->measure = gtk_center_box_measure;
+ widget_class->size_allocate = gtk_center_box_size_allocate;
+ widget_class->snapshot = gtk_center_box_snapshot;
+}
+
+static void
+gtk_center_box_init (GtkCenterBox *self)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+
+ self->start_widget = NULL;
+ self->center_widget = NULL;
+ self->end_widget = NULL;
+}
+
+GtkWidget *
+gtk_center_box_new (void)
+{
+ return GTK_WIDGET (g_object_new (GTK_TYPE_CENTER_BOX, NULL));
+}
+
+void
+gtk_center_box_set_start_widget (GtkCenterBox *self,
+ GtkWidget *child)
+{
+ if (self->start_widget)
+ gtk_widget_unparent (self->start_widget);
+
+ self->start_widget = child;
+ if (child)
+ gtk_widget_set_parent (child, GTK_WIDGET (self));
+}
+
+void
+gtk_center_box_set_center_widget (GtkCenterBox *self,
+ GtkWidget *child)
+{
+ if (self->center_widget)
+ gtk_widget_unparent (self->center_widget);
+
+ self->center_widget = child;
+ if (child)
+ gtk_widget_set_parent (child, GTK_WIDGET (self));
+}
+
+void
+gtk_center_box_set_end_widget (GtkCenterBox *self,
+ GtkWidget *child)
+{
+ if (self->end_widget)
+ gtk_widget_unparent (self->end_widget);
+
+ self->end_widget = child;
+ if (child)
+ gtk_widget_set_parent (child, GTK_WIDGET (self));
+}
+
+GtkWidget *
+gtk_center_box_get_start_widget (GtkCenterBox *self)
+{
+ return self->start_widget;
+}
+
+GtkWidget *
+gtk_center_box_get_center_widget (GtkCenterBox *self)
+{
+ return self->center_widget;
+}
+
+GtkWidget *
+gtk_center_box_get_end_widget (GtkCenterBox *self)
+{
+ return self->end_widget;
+}